<template>
  <div :class="['el-container', { 'is-vertical': isVertical }]">
    <slot></slot>
  </div>
</template>

<script>
import {
  ref,
  defineProps,
  computed,
  inject,
  getCurrentInstance,
  defineComponent,
  defineExpose,
} from "vue";

export default defineComponent({
  name: "ElContainer",
  props: {
    direction: {
      type: String,
      validator: (val) => ["horizontal", "vertical"].includes(val),
    },
  },

  setup(props, { slots }) {
    const vm = getCurrentInstance();
    const {
      proxy: { $slots },
    } = vm;

    const isVertical = computed(() => {
      if (props.direction === "vertical") {
        return true;
      }
      if (props.direction === "horizontal") {
        return false;
      }

      return $slots && $slots.default
        ? $slots.default.some((vNode) => {
            const tag = vNode.componentOptions && vNode.componentOptions.tag;
            return tag === "el-header" || tag === "el-footer";
          })
        : false;
    });

    // return: 用于暴露当前组件的 setup 函数中的数据给组件的模板，但不能被外部组件直接访问。
    //不能父子通信,只能当前组件使用,
    return {
      isVertical,
    };
    // defineExpose: 用于在 <script setup> 语法中将数据暴露给外部组件或父组件，使外部组件能够直接访问这些暴露的数据。
    //可以用于父子通信,但必须使用setup语法糖
    // defineExpose({
    //   isVertical,
    // });

    // Vue 3 中，defineExpose 只能在 <script setup> 语法糖中使用，但在传统的组件选项 API 中，你可以通过以下方式实现类似功能：
    /**
     1,  使用 return: 用于将 setup 函数中的数据和方法暴露给组件的模板，但不能直接被外部组件访问。
    2,通过 props 传递数据: 用于将数据从父组件传递给子组件。
    3,使用 $refs: 允许父组件通过引用访问子组件实例的数据和方法。
    4,通过事件机制: 子组件可以发出事件并传递数据给父组件，父组件可以监听这些事件。
    */
  },
});
</script>
